#include "aliyun_iot_func.h"

#include "datadef.h"
#include "queuedata_single.h"
#include "cJSON.h"
#include "Log.h"

namespace G_VALUE {
	int IOT_CODE = 0;
};

void event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
	uintptr_t packet_id = (uintptr_t)msg->msg;
	iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)msg->msg;

	switch (msg->event_type) {
	case IOTX_MQTT_EVENT_UNDEF:
		CLogger::createInstance()->Log(MsgInfo
			, "%s|%03d :: undefined event occur."
			, __func__, __LINE__);
		break;

	case IOTX_MQTT_EVENT_DISCONNECT:
		CLogger::createInstance()->Log(MsgInfo
			, "%s|%03d :: MQTT disconnect."
			, __func__, __LINE__);
		break;

	case IOTX_MQTT_EVENT_RECONNECT:
		CLogger::createInstance()->Log(MsgInfo
			, "%s|%03d :: MQTT reconnect."
			, __func__, __LINE__);
		break;

	case IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS:
		CLogger::createInstance()->Log(MsgInfo
			, "%s|%03d :: subscribe success, packet-id=%u"
			, __func__, __LINE__, (unsigned int)packet_id);
		break;

	case IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT:
		CLogger::createInstance()->Log(MsgInfo
			, "%s|%03d :: subscribe wait ack timeout, packet-id=%u"
			, __func__, __LINE__, (unsigned int)packet_id);
		break;

	case IOTX_MQTT_EVENT_SUBCRIBE_NACK:
		CLogger::createInstance()->Log(MsgInfo
			, "%s|%03d :: subscribe nack, packet-id=%u"
			, __func__, __LINE__, (unsigned int)packet_id);
		break;

	case IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS:
		CLogger::createInstance()->Log(MsgInfo
			, "%s|%03d :: unsubscribe success, packet-id=%u"
			, __func__, __LINE__, (unsigned int)packet_id);
		break;

	case IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT:
		CLogger::createInstance()->Log(MsgInfo
			, "%s|%03d :: unsubscribe timeout, packet-id=%u"
			, __func__, __LINE__, (unsigned int)packet_id);
		break;

	case IOTX_MQTT_EVENT_UNSUBCRIBE_NACK:
		CLogger::createInstance()->Log(MsgInfo
			, "%s|%03d :: unsubscribe nack, packet-id=%u"
			, __func__, __LINE__, (unsigned int)packet_id);
		break;

	case IOTX_MQTT_EVENT_PUBLISH_SUCCESS:
		CLogger::createInstance()->Log(MsgInfo
			, "%s|%03d :: publish success, packet-id=%u"
			, __func__, __LINE__, (unsigned int)packet_id);
		break;

	case IOTX_MQTT_EVENT_PUBLISH_TIMEOUT:
		CLogger::createInstance()->Log(MsgInfo
			, "%s|%03d :: publish timeout, packet-id=%u"
			, __func__, __LINE__, (unsigned int)packet_id);
		break;

	case IOTX_MQTT_EVENT_PUBLISH_NACK:
		CLogger::createInstance()->Log(MsgInfo
			, "%s|%03d :: publish nack, packet-id=%u"
			, __func__, __LINE__, (unsigned int)packet_id);
		break;

	case IOTX_MQTT_EVENT_PUBLISH_RECVEIVED:
	{
		int code_id = 0;
		getReplyCode(topic_info->payload,code_id);
		switch (code_id)
		{
		case 520:
		{
			G_VALUE::IOT_CODE = 520;
			CLogger::createInstance()->Log(MsgInfo
				, "device no session,need link Iot again and sub/combine device.");
		}
			break;
		case 200:
		{
			std::string topic_ = std::string(topic_info->ptopic, topic_info->topic_len);
			std::string::size_type login_pos = topic_.find(ALINK_TOPIC_DEV_LOGIN_REPLY_FLAG);
			if (std::string::npos != login_pos)
			{
				login_message_arrive(pcontext, pclient, msg);
			}
			std::string::size_type logout_pos = topic_.find(ALINK_TOPIC_DEV_LOGOUT_REPLY_FLAG);
			if (std::string::npos != logout_pos)
			{
				logout_message_arrive(pcontext, pclient, msg);
			}
			std::string::size_type post_pos = topic_.find(ALINK_TOPIC_EVENT_PRO_POST_REPLY_FLAG);
			if (std::string::npos != post_pos)
			{
				push_reply_message_arrive(pcontext,pclient,msg);
			}
			std::string::size_type set_pos = topic_.find(ALINK_TOPIC_SERVICE_PRO_SET_FLAG);
			if (std::string::npos != set_pos) {
				service_set_message_arrive(pcontext, pclient, msg);
			}
			std::string::size_type tag_up_pos = topic_.find(ALINK_TOPIC_TAG_UPDATE_REPLY_FLAG);
			if (std::string::npos != tag_up_pos) {
				tag_update_reply_arrive(pcontext, pclient, msg);
			}
			std::string::size_type tag_del_pos = topic_.find(ALINK_TOPIC_TAG_DELETE_REPLY_FLAG);
			if (std::string::npos != tag_del_pos) {
				tag_del_reply_arrive(pcontext, pclient, msg);
			}
		}
			break;
		case 0:
		{
			std::string topic_ = std::string(topic_info->ptopic, topic_info->topic_len);
			std::string::size_type set_pos = topic_.find(ALINK_TOPIC_SERVICE_PRO_SET_FLAG);
			if (std::string::npos != set_pos) {
				service_set_message_arrive(pcontext, pclient, msg);
			}
		}
			break;
		default:
			CLogger::createInstance()->Log(MsgInfo
				, "%s|%03d|%d :: topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s",
				__func__, __LINE__, code_id,
				topic_info->topic_len,
				topic_info->ptopic,
				topic_info->payload_len,
				topic_info->payload);
			break;
		}
	}
		break;

	case IOTX_MQTT_EVENT_BUFFER_OVERFLOW:
		CLogger::createInstance()->Log(MsgInfo
			, "%s|%03d :: buffer overflow, %s"
			, __func__, __LINE__, msg->msg);
		break;

	default:
		CLogger::createInstance()->Log(MsgInfo
			, "%s|%03d :: Should NOT arrive here."
			, __func__, __LINE__);
		break;
	}
};

void getReplyCode(const char* payload, int &code_id)
{
	//解析Json模型,获取Code
	try {
		cJSON *request_root = NULL, *item_propertyid = NULL;
		request_root = cJSON_Parse(payload);
		if (NULL == request_root) {
			return;
		}
		if (!cJSON_IsObject(request_root))
		{
			return;
		}
		item_propertyid = cJSON_GetObjectItem(request_root, "code");
		if (item_propertyid != NULL && cJSON_IsNumber(item_propertyid))
		{
			code_id = static_cast<int>(item_propertyid->valuedouble);
			Print_NOTICE("code id_f = %.2f, id_i= %d\n", item_propertyid->valuedouble, code_id);
		}
		cJSON_Delete(request_root);
	}
	catch (...) {
		CLogger::createInstance()->Log(MsgInfo
			, "IOTX_MQTT_EVENT_PUBLISH_RECVEIVED for code judge appear error!");
	}
};

void login_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
	iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt)msg->msg;

	/* print topic name and topic message */
	EXAMPLE_TRACE("--login_message_arrive--");
	printf_out_topic_info(ptopic_info);
	EXAMPLE_TRACE("--login_message_arrive--");
	int code_id = 0;
	getReplyCode(ptopic_info->payload, code_id);
	switch (code_id)
	{
	case 460:
		CLogger::createInstance()->Log(MsgInfo
			, "login_message_arrive error, request parameter error.");
		break;
	case 429:
		CLogger::createInstance()->Log(MsgInfo
			, "login_message_arrive error, rate limit, too many subDeviceOnline msg in one minute.");
		break;
	case 428:
		CLogger::createInstance()->Log(MsgInfo
			, "login_message_arrive error, too many subdevices under gateway.");
		break;
	case 6401:
		CLogger::createInstance()->Log(MsgInfo
			, "login_message_arrive error, topo relation not exist.");
		break;
	case 6100:
		CLogger::createInstance()->Log(MsgInfo
			, "login_message_arrive error, device not found.");
		break;
	case 521:
		CLogger::createInstance()->Log(MsgInfo
			, "login_message_arrive error, device deleted.");
		break;
	case 522:
		CLogger::createInstance()->Log(MsgInfo
			, "login_message_arrive error, device forbidden.");
		break;
	case 6287:
		CLogger::createInstance()->Log(MsgInfo
			, "login_message_arrive error, invalid sign.");
		break;
	default:
		break;
	}
};

void logout_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
	iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt)msg->msg;

	/* print topic name and topic message */
	EXAMPLE_TRACE("--logout_message_arrive--");
	printf_out_topic_info(ptopic_info);
	EXAMPLE_TRACE("--logout_message_arrive--");
	int code_id = 0;
	getReplyCode(ptopic_info->payload, code_id);
	switch (code_id)
	{
	case 460:
		CLogger::createInstance()->Log(MsgInfo
			, "logout_message_arrive error, request parameter error.");
		break;
	case 520:
		CLogger::createInstance()->Log(MsgInfo
			, "logout_message_arrive error, device no session.");
		break;
	default:
		break;
	}
};

void push_reply_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
	iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt)msg->msg;

	/* print topic name and topic message */
	EXAMPLE_TRACE("--push_reply_message_arrive--");
	printf_out_topic_info(ptopic_info);
	EXAMPLE_TRACE("--push_reply_message_arrive--");
	int code_id = 0;
	getReplyCode(ptopic_info->payload, code_id);
	switch (code_id)
	{
	case 460:
		CLogger::createInstance()->Log(MsgInfo
			, "push_reply_message_arrive error, request parameter error.");
		break;
	case 6106:
		CLogger::createInstance()->Log(MsgInfo
			, "push_reply_message_arrive error, map size must less than 200.");
		break;
	case 6313:
		CLogger::createInstance()->Log(MsgInfo
			, "push_reply_message_arrive error, tsl service not available.");
		break;
	default:
		break;
	}
};

void service_set_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
	iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt)msg->msg;
	QueueDataSingle<RCacheAliyun> *cache_from_aliyun_queue=QueueDataSingle<RCacheAliyun>::getInstance();
	// ReceiveCacheAliyunMQTT *ptr_ReceiveCacheAliyunMQTT = ReceiveCacheAliyunMQTT::getInstance();
	RCacheAliyun retDatas(std::string(ptopic_info->ptopic, ptopic_info->topic_len)
		, std::string(ptopic_info->payload, ptopic_info->payload_len));
	cache_from_aliyun_queue->add(retDatas);
	{
		/* print topic name and topic message */
		EXAMPLE_TRACE("--service_set_message_arrive--");
		printf_out_topic_info(ptopic_info);
		EXAMPLE_TRACE("--service_set_message_arrive--");
	}
};

void tag_update_reply_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
	EXAMPLE_TRACE("--tag_update_reply_arrive--");
	base_reply_arrive(pcontext, pclient, msg);
	EXAMPLE_TRACE("--tag_update_reply_arrive--");
};

void tag_del_reply_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
	EXAMPLE_TRACE("--tag_del_reply_arrive--");
	base_reply_arrive(pcontext, pclient, msg);
	EXAMPLE_TRACE("--tag_del_reply_arrive--");
};

void desired_get_reply_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
	EXAMPLE_TRACE("--desired_get_reply_arrive--");
	base_reply_arrive(pcontext, pclient, msg);
	EXAMPLE_TRACE("--desired_get_reply_arrive--");
};

void desired_del_reply_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
	EXAMPLE_TRACE("--desired_del_reply_arrive--");
	base_reply_arrive(pcontext, pclient, msg);
	EXAMPLE_TRACE("--desired_del_reply_arrive--");
};

void event_up_reply_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
	EXAMPLE_TRACE("--event_up_reply_arrive--");
	base_reply_arrive(pcontext, pclient, msg);
	EXAMPLE_TRACE("--event_up_reply_arrive--");
};

void base_reply_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
	iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt)msg->msg;
	/* print topic name and topic message */
	printf_out_topic_info(ptopic_info);
};

void printf_out_topic_info(iotx_mqtt_topic_info_pt ptopic_info)
{
	EXAMPLE_TRACE("packetId: %d", ptopic_info->packet_id);
	EXAMPLE_TRACE("Topic: '%.*s' (Length: %d)",
		ptopic_info->topic_len,
		ptopic_info->ptopic,
		ptopic_info->topic_len);
	EXAMPLE_TRACE("Payload: '%.*s' (Length: %d)",
		ptopic_info->payload_len,
		ptopic_info->payload,
		ptopic_info->payload_len);
};
